package com.zc.framework.datasource;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.util.Assert;

/**
 * Created by zc on 2016/8/30.
 */
public class DataSourceRouteInterceptor implements MethodInterceptor {

    private static final long serialVersionUID = 479391099917566432L;
    private static Logger logger = LogManager.getLogger(DataSourceRouteInterceptor.class);
    private String defaultDsName = null;

    public DataSourceRouteInterceptor() {
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Class ifc = invocation.getMethod().getDeclaringClass();
        if(ifc.isInterface()) {
            return invocation.proceed();
        } else {
            String injectedDataSource = null;
            if(invocation.getMethod().isAnnotationPresent(DynamicDataSource.class)) {
                DynamicDataSource dncDs = invocation.getMethod().getAnnotation(DynamicDataSource.class);
                injectedDataSource = dncDs.value();
            }

            if(StringUtils.isBlank(injectedDataSource)) {
                injectedDataSource = this.getDefaultDsName();
            }

            DataSourceContextHolder.setDataSource(injectedDataSource);
            logger.debug("Inject DataSource from {{}} for method {{}} invoking",
                    new Object[]{injectedDataSource, invocation.getMethod()});

            Object dncDs1;
            try {
                dncDs1 = invocation.proceed();
            } finally {
                logger.debug("Reset DataSource from {{}} for method {{}} invoking",
                        new Object[]{injectedDataSource, invocation.getMethod()});
                DataSourceContextHolder.clearDataSource();
            }

            return dncDs1;
        }
    }

    public String getDefaultDsName() {
        return this.defaultDsName;
    }

    public void setDefaultDsName(String defaultDsName) {
        Assert.notNull(defaultDsName, "dataSource cannot be null");
        this.defaultDsName = defaultDsName;
    }
}
